#include "seg.h"

#define BUFLEN 512
int kill_priority = 0;
int maxfd = -1;
fd_set master;

int main(__attribute__((unused)) int argc, __attribute__((unused)) char **argv){
    plugin *temp_plugin;
    char buf[512];
    int a,retval;
    fd_set fds;
    struct sigaction reapchildren;

    memset(&reapchildren, 0, sizeof(reapchildren));
    reapchildren.sa_flags = SA_NOCLDWAIT;
    sigaction(SIGCHLD, &reapchildren, 0);

    commands_init();
    plugins_init();
    events_init();

    FD_ZERO(&master);
    plugin_watch(term);

    for(;;){
        buf[0] = '\0';
        fds = master;
        retval = select(maxfd+1,&fds,NULL,NULL,NULL);
        if (retval == -1){
            if (errno == EINTR){
                printf("select was interrupted\n");
                continue;
            }
            error("select");
            quit();
        } else if (!retval){
            printf("timed out\n");
            continue;
        }
        for(temp_plugin = plugins; temp_plugin; temp_plugin = temp_plugin->next){
            if (FD_ISSET(temp_plugin->fd,&fds)){
                a = read(temp_plugin->fd,buf,BUFLEN);
                if (a > 0){
                    if (temp_plugin->state != STATE_RUNNING) temp_plugin->state = STATE_RUNNING;
                    if (a < BUFLEN) buf[a] = '\0';
                    else buf[BUFLEN-1] = '\0';
                    rmnl(buf);
                    cmd_run(temp_plugin,buf);
                } else {
                    plugin_kill(temp_plugin);
                }
            }
        }
    }
    return 0;
}

void plugin_watch(plugin *p){
    FD_SET(p->fd,&master);
    if (p->fd > maxfd) maxfd = p->fd;
}

void plugin_unwatch(plugin *p){
    FD_CLR(p->fd,&master);
    if (p->fd == maxfd){
        if (p->next == NULL){
            error("what the FUCK\n");
            quit();
        }
        maxfd = p->next->fd;
    }
}

void quit(void){
    tellall("dying\n");
    exit(0);
}

void cmd_quit(plugin *p){
    if (p->priority < kill_priority){
        tell(p,"unauthorized\n");
        return;
    }
    quit();
}

void error(const char *buf){
    printf("error: %s\n",buf);
}

void __debug(const char *function, int lineno, const char *fmt, ...){
    const char *format = "%s:%d DEBUG: ";
    va_list ap;

    fprintf(stderr, format, function, lineno);
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);
}
